const request = require('request');
const fs = require('fs');
const path = require('path');
const moments = require('moment');
const logTable = require('@xdooi/consoletable');
//
class Common {
    // 日期范围
    dateArr(max: number = 7): Array<string> {
        // 默认最近七天
        let arr = [];
        // let date = 
        for (let i = 0; i < max; i++) {
            arr.push(
                moments()
                    .add(-+i, 'd')
                    .format('YYYY-MM-DD')
            );
        }
        return arr.reverse();
    }
    // 数组转对象
    arrOfobj<T>(arr: Array<T>) {
        const obj: { [PropKey: string]: any } = {}
        arr.forEach((item, index) => {
            obj[index] = item
        })
        return obj
    }
    // stop阻塞函数
    stop(delay: number) {
        return new Promise((reslove, reject) => {
            setTimeout(reslove, delay)
        })
    }
}

interface GetGiteeFormat {
    infos: Array<{ NickName: string, UserName: string }>,
    max?: number
}
type ArrayObj = Array<{ [propName: string]: any }>
type Obj = { [propName: string]: any }

// 获取gitee信息
class GetGitee extends Common {
    public dates: Array<string>
    public infos: Array<{ NickName: string, UserName: string }>
    public scope: number | undefined
    public baseUrl = 'https://gitee.com/'
    // public dataObj:{}
    constructor(options: GetGiteeFormat) {
        super()
        this.infos = options.infos
        this.scope = options.max
        this.dates = []
        this.init()
    }
    init() {
        this.dates = this.scope ? this.dateArr(this.scope) : this.dateArr()
    }
    async start() {
        // 所有的数据
        const allData: Array<{ [propName: string]: any }> = []
        for (let i = 0; i < this.infos.length; i++) {
            const info = this.infos[i]
            try {
                const data: Obj = await this.getInfo(info) as Obj
                allData.push(data)
            } catch (err) {
                if (err instanceof Error) {
                    console.log(err.message);
                    return false
                }
                allData.push(err as Obj)
            }
        }
        // 数据排序
        allData.sort((a, b) => Number(a.count) - Number(b.count))
        allData.forEach((item, index) => item['xuhao'] = index.toString())
        this.tableLog(allData)

    }
    getInfo(info: { NickName: string, UserName: string }) {
        // 爬取配置信息
        const options = {
            uri: this.baseUrl + info.UserName,
            headers: {
                'User-Agent':
                    'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/105.0.0.0 Safari/537.36 Edg/105.0.1343.53',
            },
            strictSSL: false,
        };

        // 正则表达式，匹配该用户gitee代码提交次数
        const reg = eval(`/(?<=data-content=').*(?=个贡献：(${this.dates.join('|')}))/g`);

        return new Promise((resolve, reject) => {
            request(options, <T>(err: T, res: T, body: T) => {
                if (err) return reject(err)
                const data = (body + '').match(reg)
                // 没有数据时
                if (!data) {
                    console.log(`${info.NickName} 的gitee用户名：${info.UserName}，爬取失败：用户不存在`);
                    resolve({
                        ...this.arrOfobj(this.dates.map(item => 'none')),
                        name: info.NickName,
                        count: '0'
                    });

                    return false
                }
                // 数据获取成功
                console.log(`${info.NickName} 的gitee用户：${info.UserName}，爬取成功 `);
                resolve({
                    ...data,
                    name: info.NickName,
                    count: data.reduce((pre, cur) => pre + Number(cur), 0).toString()
                })
            })
        })
    }
    tableLog(data: { [PropName: string]: any }[]) {
        logTable.drawTable(
            [
                {
                    ...this.arrOfobj(this.dates),
                    name: '姓名',
                    count: 'count',
                    xuhao: '序号',
                },
                ...data,
            ],
            { head: false }
        );
    }
}
const file = '../src/ceishi.json'
const infos = JSON.parse(fs.readFileSync(path.join(__dirname, file), 'utf-8'))

const gitee = new GetGitee({ infos, max: 7 })
gitee.start()


